package top.chmin.project.cloud.common.entity.column.relation.auto;

// field import auto
// #bind.field.targetTableCode#

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.chmin.project.cloud.common.entity.Page;
import top.chmin.project.cloud.common.entity.auto.Entity;
import top.chmin.project.cloud.common.entity.auto.EntityDao;
import top.chmin.project.cloud.common.entity.auto.EntityFPC;
import top.chmin.project.cloud.common.entity.column.auto.EntityColumn;
import top.chmin.project.cloud.common.entity.column.auto.EntityColumnDao;
import top.chmin.project.cloud.common.entity.column.auto.EntityColumnFPC;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * chmin
 * 2023-12-27 15:15:42
 * cloud-builder
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class EntityColumnRelationService {

    @Resource
    EntityColumnRelationPlugin plugin;

    @Resource
    EntityColumnRelationDao entityColumnRelationDao;

    // field labelDao auto
// #bind.field.targetTableCode#
    @Resource
    EntityDao entityDao;
// $bind.field.targetTableCode$

    // #bind.field.targetFieldCode#
    @Resource
    EntityColumnDao entityColumnDao;
// $bind.field.targetFieldCode$


    public int save(EntityColumnRelationSave.Param param) {
        plugin.checkSave(param);
        EntityColumnRelation entityColumnRelation = BeanUtil.toBean(param, EntityColumnRelation.class);
        plugin.beforeSave(entityColumnRelation);
        int result = entityColumnRelationDao.save(entityColumnRelation);
        plugin.afterSave(param, entityColumnRelation, result);
        return result;
    }

    public int updateById(EntityColumnRelationUpdateById.Param param) {
        plugin.checkUpdateById(param);
        EntityColumnRelation entityColumnRelation = BeanUtil.toBean(param, EntityColumnRelation.class);
        plugin.beforeUpdateById(entityColumnRelation);
        int result = entityColumnRelationDao.updateById(entityColumnRelation);
        plugin.afterUpdateById(param, entityColumnRelation, result);
        return result;
    }

    public int deleteById(EntityColumnRelationDeleteById.Param param) {
        plugin.checkDeleteById(param);
        int result = entityColumnRelationDao.deleteById(param.getId());
        plugin.afterDeleteById(param, result);
        return result;
    }

    public EntityColumnRelationSelectById.Result selectById(EntityColumnRelationSelectById.Param param) {
        plugin.checkSelectById(param);
        EntityColumnRelationFPC fpc = new EntityColumnRelationFPC().id().eq(param.getId());
        plugin.beforeSelectById(param, fpc);
        EntityColumnRelationSelectById.Result result = entityColumnRelationDao.getFirst(fpc.toCondition(), EntityColumnRelationSelectById.Result.class);
        plugin.afterSelectById(param, result);
        return result;
    }

    public Page<EntityColumnRelationSelectPage.Result> selectPage(EntityColumnRelationSelectPage.Param param) {
        plugin.checkSelectPage(param);
        EntityColumnRelationFPC fpc = new EntityColumnRelationFPC();
        fpc = param.isDesc() ? fpc.id().desc() : fpc.id().asc();
        plugin.beforeSelectPage(param, fpc);
        Page<EntityColumnRelationSelectPage.Result> result = entityColumnRelationDao.getPageByCondition(fpc.toCondition(), EntityColumnRelationSelectPage.Result.class);
// field label auto
// #bind.field.sourceTableCode#
        if (CollectionUtil.isNotEmpty(result.getList())) {
            List<String> sourceTableCodeList = result.getList().stream()
                    .map(EntityColumnRelationSelectPage.Result::getSourceTableCode)
                    .toList();
            Stream<Entity> sourceTableCodeStream = entityDao.getStreamByCondition(
                    new EntityFPC()
                            .forDistinct()
                            .tableCode().in(sourceTableCodeList)
                            .toCondition()
            );
            Map<String, Entity> sourceTableCodeMap = sourceTableCodeStream.collect(Collectors.toMap(
                    Entity::getTableCode,
                    t -> t
            ));
            result.getList().forEach(r -> {
                Entity entity = sourceTableCodeMap.get(r.getSourceTableCode());
                r.setSourceTableCodeLabel(entity == null ? null : entity.getTableName());
            });
        }
// $bind.field.sourceTableCode$

// #bind.field.targetTableCode#
        if (CollectionUtil.isNotEmpty(result.getList())) {
            List<String> targetTableCodeList = result.getList().stream()
                    .map(EntityColumnRelationSelectPage.Result::getTargetTableCode)
                    .toList();
            Stream<Entity> targetTableCodeStream = entityDao.getStreamByCondition(
                    new EntityFPC()
                            .forDistinct()
                            .tableCode().in(targetTableCodeList)
                            .toCondition()
            );
            Map<String, Entity> targetTableCodeMap = targetTableCodeStream.collect(Collectors.toMap(
                    Entity::getTableCode,
                    t -> t
            ));
            result.getList().forEach(r -> {
                Entity entity = targetTableCodeMap.get(r.getTargetTableCode());
                r.setTargetTableCodeLabel(entity == null ? null : entity.getTableName());
            });
        }
// $bind.field.targetTableCode$

// #bind.field.sourceFieldCode#
        if (CollectionUtil.isNotEmpty(result.getList())) {
            List<String> sourceFieldCodeList = result.getList().stream()
                    .map(EntityColumnRelationSelectPage.Result::getSourceFieldCode)
                    .toList();
            Stream<EntityColumn> sourceFieldCodeStream = entityColumnDao.getStreamByCondition(
                    new EntityColumnFPC()
                            .forDistinct()
                            .fieldCode().in(sourceFieldCodeList)
                            .toCondition()
            );
            Map<String, EntityColumn> sourceFieldCodeMap = sourceFieldCodeStream.collect(Collectors.toMap(
                    EntityColumn::getFieldCode,
                    t -> t
            ));
            result.getList().forEach(r -> {
                EntityColumn entityColumn = sourceFieldCodeMap.get(r.getSourceFieldCode());
                r.setSourceFieldCodeLabel(entityColumn == null ? null : entityColumn.getFieldName());
            });
        }
// $bind.field.sourceFieldCode$

// #bind.field.targetFieldCode#
        if (CollectionUtil.isNotEmpty(result.getList())) {
            List<String> targetFieldCodeList = result.getList().stream()
                    .map(EntityColumnRelationSelectPage.Result::getTargetFieldCode)
                    .toList();
            Stream<EntityColumn> targetFieldCodeStream = entityColumnDao.getStreamByCondition(
                    new EntityColumnFPC()
                            .forDistinct()
                            .fieldCode().in(targetFieldCodeList)
                            .toCondition()
            );
            Map<String, EntityColumn> targetFieldCodeMap = targetFieldCodeStream.collect(Collectors.toMap(
                    EntityColumn::getFieldCode,
                    t -> t
            ));
            result.getList().forEach(r -> {
                EntityColumn entityColumn = targetFieldCodeMap.get(r.getTargetFieldCode());
                r.setTargetFieldCodeLabel(entityColumn == null ? null : entityColumn.getFieldName());
            });
        }
// $bind.field.targetFieldCode$

        plugin.afterSelectPage(param, result);
        return result;
    }

// entity select auto

// entity search auto

}
